﻿using System.Windows.Input;
using YourWorld.Common;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Composite.Presentation.Commands;
using Microsoft.Practices.Composite.Regions;
using MainGameModule.Views;
using BusinessObjects;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System;
using System.Linq;
using MainGameModule.Models;
using YourWorld.Common.GreenWorldEntitiesService;
using YourWorld.Common.Infrastucture.Events;

namespace MainGameModule.ViewModels
{
    public class GameControlsViewModel : ViewModelBase
    {
        private IUnityContainer container;
        private IRegionManager regionManager;

        private UserBadge selectedBadge;
        private ObservableCollection<UserBadge> possessedBadges;
        private ObservableCollection<Event> takenQuests;
        private Player player;

        private const double HealthMaxValue = 200;
        private const double ExperienceMaxValue = 200;

        private double health = HealthMaxValue;
        private double experience = 0;

        public GameControlsViewModel( IUnityContainer container, IRegionManager regionManager )
        {
            this.container = container;
            this.regionManager = regionManager;

            this.BrowseEventsCommand = new DelegateCommand<object>( this.BrowseEvents );
            this.ShowBadgesCommand = new DelegateCommand<string>( this.ShowBadges );
            this.ShowQuizCommand = new DelegateCommand<string>( this.ShowQuiz );

            this.ShowBadgesLightCommand = new DelegateCommand<string>( this.ShowBadgesLight );
            this.ShowQuestsLightCommand = new DelegateCommand<string>( this.ShowQuestsLight );
            this.ShowTutorialCommand = new DelegateCommand<string>( this.ShowTutorial );
            this.ShowWallOfFameCommand = new DelegateCommand<string>( this.ShowWallOfFame );
            this.ShowPartnersCommand = new DelegateCommand<string>(this.ShowPartners);

            PlayerStatusManager.Instance.HealthChanged += new Action(PlayerHealthChanged);
            PlayerStatusManager.Instance.ExperienceChanged += new Action<int>(ExperienceChanged);
        }

        public GameMainViewModel Game
        {
            get
            {
                GameMainViewModel game = this.container.Resolve<GameMainViewModel>();
                return game;
            }
        }

        public Player Player
        {
            get
            {
                return this.player;
            }
            set
            {
                if ( this.player == value )
                    return;

                this.player = value;
                this.NotifyPropertyChanged( "Player" );
            }
        }

        public double Health
        {
            get
            {
                return this.health;
            }
            set
            {
                if (this.health == value || value < 0)
                    return;

                this.health = value;
                this.NotifyPropertyChanged("Health");
            }
        }

        public double Experience
        {
            get
            {
                return this.experience;
            }
            set
            {
                if (this.experience == value || value < 0)
                    return;

                this.experience = value;
                this.NotifyPropertyChanged("Experience");
            }
        }

        public ICommand ShowBadgesLightCommand
        {
            get;
            set;
        }

        public ICommand ShowQuestsLightCommand
        {
            get;
            set;
        }

        public ICommand BrowseEventsCommand
        {
            get;
            private set;
        }

        public ICommand ShowBadgesCommand
        {
            get;
            private set;
        }

        public ICommand ShowQuizCommand
        {
            get;
            private set;
        }

        public ICommand ShowTutorialCommand
        {
            get;
            private set;
        }

        public ICommand ShowWallOfFameCommand
        {
            get;
            private set;
        }

        public ICommand ShowPartnersCommand
        {
            get;
            private set;
        }

        private void ShowPartners(string notUsed)
        {
            if (this.regionManager.Regions[RegionNames.GamePopUpRegion].Views.Contains(this.container.Resolve<Partners>()) == false)
                this.regionManager.RegisterViewWithRegion(RegionNames.GamePopUpRegion, typeof(Partners));
            else
                this.regionManager.Regions[RegionNames.GamePopUpRegion].Activate(this.container.Resolve<Partners>());
        }

        private void ShowTutorial( string notUsed )
        {
            if ( this.regionManager.Regions[RegionNames.GamePopUpRegion].Views.Contains( this.container.Resolve<TutorialView>() ) == false )
                this.regionManager.RegisterViewWithRegion( RegionNames.GamePopUpRegion, typeof( TutorialView ) );
            else
                this.regionManager.Regions[RegionNames.GamePopUpRegion].Activate( this.container.Resolve<TutorialView>() );
        }

        private void ShowWallOfFame( string notUsed )
        {
            WallOfFameView view = this.container.Resolve<WallOfFameView>();
            if ( this.regionManager.Regions[RegionNames.GamePopUpRegion].Views.Contains( view ) == false )
                this.regionManager.RegisterViewWithRegion( RegionNames.GamePopUpRegion, typeof( WallOfFameView ) );
            else
                this.regionManager.Regions[RegionNames.GamePopUpRegion].Activate( view );
        }

        private void ShowBadgesLight( string notUsed )
        {
            if ( this.PossessedBadges != null && this.PossessedBadges.Count > 0 )
            {
                this.PossessedBadges.Clear();
            }
            else
            {
                this.InitializeBadges();
            }
        }

        private void ShowQuestsLight( string notUsed )
        {
            if ( this.TakenQuests != null && this.TakenQuests.Count > 0 )
            {
                this.TakenQuests.Clear();
            }
            else
            {
                this.InitializeQuests();
            }
        }

        private void ShowQuiz( string notUsed )
        {
            if ( this.regionManager.Regions[RegionNames.GamePopUpRegion].Views.Contains( this.container.Resolve<QuizView>() ) == false )
                this.regionManager.RegisterViewWithRegion( RegionNames.GamePopUpRegion, typeof( QuizView ) );
            else
                this.regionManager.Regions[RegionNames.GamePopUpRegion].Activate( this.container.Resolve<QuizView>() );
        }

        private void ShowBadges( string notUsed )
        {
            if ( this.regionManager.Regions[RegionNames.GamePopUpRegion].Views.Contains( this.container.Resolve<BadgesView>() ) == false )
                this.regionManager.RegisterViewWithRegion( RegionNames.GamePopUpRegion, typeof( BadgesView ) );
            else
                this.regionManager.Regions[RegionNames.GamePopUpRegion].Activate( this.container.Resolve<BadgesView>() );
        }

        private void BrowseEvents( object o )
        {
            if ( this.regionManager.Regions[RegionNames.GamePopUpRegion].Views.Contains( this.container.Resolve<GameEventsView>() ) == false )
                this.regionManager.RegisterViewWithRegion( RegionNames.GamePopUpRegion, typeof( GameEventsView ) );
            else
                this.regionManager.Regions[RegionNames.GamePopUpRegion].Activate( this.container.Resolve<GameEventsView>() );
        }

        public ObservableCollection<UserBadge> PossessedBadges
        {
            get
            {
                if ( this.possessedBadges == null )
                    this.possessedBadges = new ObservableCollection<UserBadge>();

                return this.possessedBadges;
            }
            set
            {
                if ( this.possessedBadges == value )
                    return;

                this.possessedBadges = value;
                this.NotifyPropertyChanged( "PossessedBadges" );
            }
        }

        public ObservableCollection<Event> TakenQuests
        {
            get
            {
                if ( this.takenQuests == null )
                    this.takenQuests = new ObservableCollection<Event>();

                return this.takenQuests;
            }
            set
            {
                if ( this.takenQuests == value )
                    return;

                this.takenQuests = value;
                this.NotifyPropertyChanged( "TakenQuests" );
            }
        }

        public UserBadge SelectedBadge
        {
            get { return this.selectedBadge; }
            set
            {
                if ( this.selectedBadge != value )
                {
                    this.selectedBadge = value;
                    this.NotifyPropertyChanged( "SelectedBadge" );
                }
            }
        }

        public void PlayerHealthChanged()
        {
            this.Health = PlayerStatusManager.Instance.Health;
        }

        public void ExperienceChanged(int experienceToAdd)
        {
            this.Experience += experienceToAdd;

            if (this.Experience == ExperienceMaxValue)
            {
                this.Experience = 0;
                GameMainViewModel mainGame = this.container.Resolve<GameMainViewModel>();
                mainGame.Player.Level++;
                mainGame.Player.Experience += (int)ExperienceMaxValue;
                PlayersRepository.Instance.SavePlayerExperience(mainGame.Player.Id, mainGame.Player.Experience, null);
                PlayersRepository.Instance.SavePlayerLevel(mainGame.Player.Id, mainGame.Player.Level, null);
                EventService.Aggregator.GetEvent<LevelFinished>().Publish(mainGame.Player.Level);
            }
        }

        private void InitializeBadges()
        {
            this.PossessedBadges = new ObservableCollection<UserBadge>();
            GameMainViewModel gameMain = this.container.Resolve<GameMainViewModel>();

            List<int> myBadgesIds = new List<int>();

            if ( String.IsNullOrEmpty( gameMain.Player.Badges ) == false )
            {
                string possessed = gameMain.Player.Badges;

                List<string> stringIds = possessed.Split( ',' ).ToList();

                foreach ( string id in stringIds )
                {
                    int result = -1;
                    if ( Int32.TryParse( id, out result ) )
                    {
                        myBadgesIds.Add( result );
                    }
                }
            }

            foreach ( Badge badge in BadgesRepository.Instance.Badges.Where( b => myBadgesIds.Contains( b.ID ) ) )
            {
                UserBadge userBadge = new UserBadge()
                {
                    Id = badge.ID,
                    Image = badge.Image,
                    TargetItems = badge.MinimumItems,
                    Description = badge.Description,
                };

                this.PossessedBadges.Add( userBadge );
            }
        }

        private void InitializeQuests()
        {
            this.TakenQuests = new ObservableCollection<Event>();
            GameMainViewModel gameMain = this.container.Resolve<GameMainViewModel>();

            foreach ( int questId in this.Split( gameMain.Player.Quests ) )
            {
                Event currQuest = RegionObjectsRepository.Instance.EventsList.Where( e => e.Id == questId ).FirstOrDefault();
                if ( currQuest != null )
                {
                    Event newQuest = new Event()
                    {
                        Description = currQuest.Description,
                        Image = currQuest.Image,
                    };
                    this.TakenQuests.Add( newQuest );
                }
            }
        }

        private List<int> Split( string ids )
        {
            List<int> resultIds = new List<int>();

            if ( String.IsNullOrEmpty( ids ) == false )
            {
                List<string> stringIds = ids.Split( ',' ).ToList();

                foreach ( string id in stringIds )
                {
                    int result = -1;
                    if ( Int32.TryParse( id, out result ) )
                    {
                        resultIds.Add( result );
                    }
                }
            }

            return resultIds;
        }
    }
}
